import glob
import importlib
import inspect
import json
import os

from utils.file import get_root_path
from websocket.msghandler import MessageType


def build_folder_dict(folder_path):
    """
    返回指定文件夹下的所有文件夹和这些文件夹下的文件
    :param folder_path:
    :return:
    """
    folder_dict = {}

    with os.scandir(folder_path) as entries:
        for entry in entries:
            if entry.is_dir():
                folder_dict[entry.name] = [sub_entry.name[:-3] for sub_entry in os.scandir(entry.path) if
                                           sub_entry.is_file() and sub_entry.name.endswith('.py')
                                           and sub_entry.name != '__init__.py'
                                           ]
    folder_dict.pop('__pycache__')
    return folder_dict


def class_json(prefix):
    """
    # 通过文件名加载模块
    :param prefix:
    :return:
    """
    # 存储所有类的列表
    folder_dict = build_folder_dict(os.path.join(get_root_path(), prefix))
    all_classes = {}
    for one_type, values in folder_dict.items():
        type_classes = []
        for value in values:
            module_name = '.'.join([prefix, one_type, value])
            classes = get_class_info(module_name)
            # 将当前文件中的类添加到总的类列表
            type_classes.append(classes[0])
        # all_classes.append({"one_type": one_type, 'data': type_classes})
        all_classes[one_type] = type_classes
    return all_classes


def get_indicators() -> dict:
    """
    获取indicators下的指标类数据
    :return:
    """
    # 指定文件夹路径和文件扩展名
    folder_path = get_root_path() + r'\indicators'
    file_extension = '*.py'  # 指定扩展名，例如 txt、csv 等
    all_classes = {}
    # 构建文件搜索路径
    search_path = os.path.join(folder_path, file_extension)

    # 遍历匹配的文件
    for file_path in glob.glob(search_path):
        # 获取文件名
        file_name = os.path.basename(file_path)

        # 判断文件名不是 "__init__.py"
        if file_name != "__init__.py":
            file_name = file_name[:-3]
            module_name = '.'.join(['indicators', file_name])
            classes = get_class_info(module_name)
            file_name = file_name.upper()
            all_classes[file_name] = classes[0]
    return all_classes


def get_class_info(module_name):
    module = importlib.import_module(module_name)
    # 获取模块中定义的所有类，且只选取来自当前模块的类
    classes = [{"name": member[0],
                "cls": member[1],
                "params": getattr(member[1], 'parameters', [])}
               for member in inspect.getmembers(module, inspect.isclass)
               if inspect.getmodule(member[1]) == module]
    return classes


class InitHandler:
    """
    用于socket初始化连接时，生成网页的渲染数据
    """
    algorithms_data = class_json(prefix='algorithms')
    problems_data = class_json(prefix='problems')
    indicators = get_indicators()

    @classmethod
    def handle(cls):
        return json.dumps({
            'messageType': MessageType.INIT_RENDER_MSG.value,
            'algorithms_data': cls.algorithms_data,
            'problems_data': cls.problems_data,
            'indicators': cls.indicators,
        }, cls=CustomEncoder)


# 自定义JSON编码器
class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, type):
            return class_to_string(obj)
        return super().default(obj)


def class_to_string(obj):
    return f"{obj.__module__}.{obj.__name__}"
